<?php

namespace App\Service\GuanyuanSSO;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;

class FeishuService
{
    public static $appId;

    public static function setAppId($appId)
    {
        static::$appId = $appId;
    }

    public static function getAppId()
    {
        return static::$appId ?? config('guanyuan-sso.feishu.appId');
    }

    public static function accessToken()
    {
        $appId     =  self::getAppId();
        $appSecret = config('guanyuan-sso.feishu.' . $appId . '.appSecret');

        $cacheKey       = "feishu_app_access_token_{$appId}";
        $appAccessToken = Cache::get($cacheKey);
        if (null !== $appAccessToken) {
            return $appAccessToken;
        }

        $response = Http::withHeaders([
            'Content-Type' => 'application/json; charset=utf-8',
        ])->post(
            'https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal',
            [
                'app_id'     => $appId,
                'app_secret' => $appSecret
            ]
        );

        $arr = json_decode($response->body(), true);
        if (JSON_ERROR_NONE !== json_last_error()) {
            return '';
        }

        $appAccessToken = $arr['app_access_token'];
        Cache::put($cacheKey, $appAccessToken, max(0, $arr['expire'] - 60));
        Cache::put("feishu_tenant_access_token_{$appId}", $arr['tenant_access_token'], max(0, $arr['expire'] - 60));
        return $appAccessToken;
    }

    public static function loginByCode(string $code)
    {
        /**
         * [
         * "code" => 0
         * "msg" => "success"
         * "data" => array:8 [
         * "access_token" => "u-gusDkUIvmYH0C1DQtKZy9e"
         * "employee_id" => "g18e5a8f"
         * "expires_in" => 1643256300
         * "open_id" => "ou_c90f808b045a43f97990bd2a1fd0707b"
         * "refresh_token" => "ur-K9SpECtrNG4UC0OoqKzmkc"
         * "session_key" => "759c3cfba3065b3dcd35326ff3ea936e"
         * "tenant_key" => "13a5aac7558d5740"
         * "union_id" => "ou_eb261923e1806da1bb43fc4bb339da95"
         * ]
         * ]
         */
        return Http::withHeaders(['Content-Type' => 'application/json; charset=utf-8'])
                   ->withToken(static::accessToken())
                   ->post('https://open.feishu.cn/open-apis/authen/v1/access_token', [
                       'grant_type' => 'authorization_code',
                       'code'       => $code,
                   ])->json();
    }

    //通过ID获取用户信息
    public static function getUserInfoByFeishuId($feishuId)
    {
        return Http::withHeaders(['Content-Type' => 'application/json; charset=utf-8'])
                   ->withToken(static::accessToken())
                   ->get('https://open.feishu.cn/open-apis/contact/v3/users/' . $feishuId,
                       ['user_id_type' => 'user_id'])->json();
    }

    public static function getDepartmentName($department_ids)
    {
        if (!count($department_ids)) {
            return '';
        }
        $departmentInfo = Http::withHeaders(['Content-Type' => 'application/json; charset=utf-8'])
                              ->withToken(static::accessToken())
                              ->get('https://open.feishu.cn/open-apis/contact/v3/departments/parent', [
                                  'department_id' => $department_ids[0],
                              ])->json();

        if (!isset($departmentInfo['code']) || !isset($departmentInfo['data']['items'])) {
            return '';
        }

        if ($departmentInfo['code'] != 0) {
            return '';
        }

        $departmentName = '';
        foreach ($departmentInfo['data']['items'] as $item) {
            if ($item['parent_department_id'] == 0) {
                $departmentName = $item['name'];
            }
        }
        return $departmentName;
    }

    public static function getDepartment($departmentId)
    {
        if (!mb_strlen($departmentId)) {
            return '';
        }
        return Http::withHeaders(['Content-Type' => 'application/json; charset=utf-8'])
                   ->withToken(self::accessToken())
                   ->get('https://open.feishu.cn/open-apis/contact/v3/departments/' . $departmentId)->json();
    }

    /**
     * 生成观远 SSO 地址
     *
     */
    public static function makeGuanyuanSSOUrl(string $userId)
    {
        //需要提供的数据
        $ssoToken = [
            'domainId'       => 'guanbi',
            'externalUserId' => $userId,
            'timestamp'      => time(), //如果传timestamp参数，则认为ssoToken有效期为5分钟；不传，则ssoToken永久有效，不会过期
        ];

        //私钥加密后的数据
        try {
            openssl_private_encrypt(json_encode($ssoToken), $encrypted, config('guanyuan-sso.privateKey'));
        } catch (\Exception $exception) {
            throw new \Exception('Openssl_private_encrypt (): key参数不是一个有效的私钥');
        }
        //加密后的内容通常含有特殊字符，需要 base64 + hex 编码转换下
        $encrypted = bin2hex(base64_encode($encrypted));

        //生成URL
        if (self::isMobile()) {
            $url = config('guanyuan-sso.mobileUrl');
        } else {
            $url = config('guanyuan-sso.pcUrl');
        }

        return $url . '?provider=' . config('guanyuan-sso.providerName') . '&ssoToken=' . $encrypted;
    }


    /**
     * 生成飞书授权地址
     *
     */
    public static function makeAuthUrl()
    {
        $url = 'https://open.feishu.cn/open-apis/authen/v1/index?redirect_uri={REDIRECT_URI}&app_id={APPID}&state={STATE}';

        $params = [
            '{REDIRECT_URI}',
            '{APPID}',
            '{STATE}'
        ];

        $appId = self::getAppId();

        $values = [
            urlencode($_SERVER['APP_URL'] . 'guanyuanSSO/login?app_id=' . $appId),
            $appId,
            ''
        ];

        return str_replace($params, $values, $url);
    }


    /**
     * 通过飞书userId 获取观远 SSO 用户 ID
     *
     */
    public static function getSSOUserId($feishuUserId, $departmentName = "")
    {
        $mapping = config('guanyuan-sso.accountList');
        foreach ($mapping['userList'] as $userId => $feishuUserIds) {
            if (in_array($feishuUserId, $feishuUserIds)) {
                return $userId;
            }
        }

        if (strlen($departmentName) > 0 && isset($mapping['departmentList'][$departmentName])) {
            return $mapping['departmentList'][$departmentName];
        }

        return '';
    }

    public static function isMobile()
    {
        // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
        if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
            return true;
        }

        //如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
        if (isset($_SERVER['HTTP_VIA'])) {
            return stristr($_SERVER['HTTP_VIA'], 'wap') ? true : false;
        }

        //判断手机发送的客户端标志,兼容性有待提高
        if (isset($_SERVER['HTTP_USER_AGENT'])) {
            $clientkeywords = array(
                'nokia',
                'sony',
                'ericsson',
                'mot',
                'samsung',
                'htc',
                'sgh',
                'lg',
                'sharp',
                'sie-',
                'philips',
                'panasonic',
                'alcatel',
                'lenovo',
                'iphone',
                'ipod',
                'blackberry',
                'meizu',
                'android',
                'netfront',
                'symbian',
                'ucweb',
                'windowsce',
                'palm',
                'operamini',
                'operamobi',
                'openwave',
                'nexusone',
                'cldc',
                'midp',
                'wap',
                'mobile',
            );

            //从HTTP_USER_AGENT中查找手机浏览器的关键字
            if (preg_match("/(" . implode('|', $clientkeywords) . ")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) {
                return true;
            }
        }

        return false;

    }

}
